
const _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault');

exports.__esModule = true;
exports.default = void 0;

const _utils = require('../utils');

const _number = require('../utils/format/number');

const _event = require('../utils/dom/event');

const _popup = require('../mixins/popup');

const _touch = require('../mixins/touch');

const _icon = _interopRequireDefault(require('../icon'));

const _image = _interopRequireDefault(require('../image'));

const _swipe = _interopRequireDefault(require('../swipe'));

const _loading = _interopRequireDefault(require('../loading'));

const _swipeItem = _interopRequireDefault(require('../swipe-item'));

// Utils
// Mixins
// Components
const _createNamespace = (0, _utils.createNamespace)('image-preview');
const createComponent = _createNamespace[0];
const bem = _createNamespace[1];

const DOUBLE_CLICK_INTERVAL = 250;

function getDistance(touches) {
  return Math.sqrt(Math.pow(touches[0].clientX - touches[1].clientX, 2) + Math.pow(touches[0].clientY - touches[1].clientY, 2));
}

const _default2 = createComponent({
  mixins: [(0, _popup.PopupMixin)({
    skipToggleEvent: true,
  }), _touch.TouchMixin],
  props: {
    className: null,
    asyncClose: Boolean,
    showIndicators: Boolean,
    images: {
      type: Array,
      default: function _default() {
        return [];
      },
    },
    loop: {
      type: Boolean,
      default: true,
    },
    swipeDuration: {
      type: [Number, String],
      default: 500,
    },
    overlay: {
      type: Boolean,
      default: true,
    },
    showIndex: {
      type: Boolean,
      default: true,
    },
    startPosition: {
      type: [Number, String],
      default: 0,
    },
    minZoom: {
      type: [Number, String],
      default: 1 / 3,
    },
    maxZoom: {
      type: [Number, String],
      default: 3,
    },
    overlayClass: {
      type: String,
      default: bem('overlay'),
    },
    closeable: Boolean,
    closeIcon: {
      type: String,
      default: 'clear',
    },
    closeIconPosition: {
      type: String,
      default: 'top-right',
    },
  },
  data: function data() {
    return {
      scale: 1,
      moveX: 0,
      moveY: 0,
      active: 0,
      moving: false,
      zooming: false,
      doubleClickTimer: null,
    };
  },
  computed: {
    imageStyle: function imageStyle() {
      const { scale } = this;
      const style = {
        transitionDuration: this.zooming || this.moving ? '0s' : '.3s',
      };

      if (scale !== 1) {
        style.transform = `scale3d(${scale}, ${scale}, 1) translate(${this.moveX / scale}px, ${this.moveY / scale}px)`;
      }

      return style;
    },
  },
  watch: {
    startPosition: 'setActive',
    value: function value(val) {
      const _this = this;

      if (val) {
        this.setActive(+this.startPosition);
        this.$nextTick(() => {
          _this.$refs.swipe.swipeTo(+_this.startPosition, {
            immediate: true,
          });
        });
      } else {
        this.$emit('close', {
          index: this.active,
          url: this.images[this.active],
        });
      }
    },
    shouldRender: {
      handler: function handler(val) {
        const _this2 = this;

        if (val) {
          this.$nextTick(() => {
            const swipe = _this2.$refs.swipe.$el;
            (0, _event.on)(swipe, 'touchstart', _this2.onWrapperTouchStart);
            (0, _event.on)(swipe, 'touchmove', _event.preventDefault);
            (0, _event.on)(swipe, 'touchend', _this2.onWrapperTouchEnd);
            (0, _event.on)(swipe, 'touchcancel', _this2.onWrapperTouchEnd);
          });
        }
      },
      immediate: true,
    },
  },
  methods: {
    emitClose: function emitClose() {
      if (!this.asyncClose) {
        this.$emit('input', false);
      }
    },
    onWrapperTouchStart: function onWrapperTouchStart() {
      this.touchStartTime = new Date();
    },
    onWrapperTouchEnd: function onWrapperTouchEnd(event) {
      const _this3 = this;

      (0, _event.preventDefault)(event);
      const deltaTime = new Date() - this.touchStartTime;

      const _ref = this.$refs.swipe || {};
      const _ref$offsetX = _ref.offsetX;
      const offsetX = _ref$offsetX === void 0 ? 0 : _ref$offsetX;
      const _ref$offsetY = _ref.offsetY;
      const offsetY = _ref$offsetY === void 0 ? 0 : _ref$offsetY; // prevent long tap to close component


      if (deltaTime < DOUBLE_CLICK_INTERVAL && offsetX < 10 && offsetY < 10) {
        if (!this.doubleClickTimer) {
          this.doubleClickTimer = setTimeout(() => {
            _this3.emitClose();

            _this3.doubleClickTimer = null;
          }, DOUBLE_CLICK_INTERVAL);
        } else {
          clearTimeout(this.doubleClickTimer);
          this.doubleClickTimer = null;
          this.toggleScale();
        }
      }
    },
    startMove: function startMove(event) {
      const image = event.currentTarget;
      const rect = image.getBoundingClientRect();
      const winWidth = window.innerWidth;
      const winHeight = window.innerHeight;
      this.touchStart(event);
      this.moving = true;
      this.startMoveX = this.moveX;
      this.startMoveY = this.moveY;
      this.maxMoveX = Math.max(0, (rect.width - winWidth) / 2);
      this.maxMoveY = Math.max(0, (rect.height - winHeight) / 2);
    },
    startZoom: function startZoom(event) {
      this.moving = false;
      this.zooming = true;
      this.startScale = this.scale;
      this.startDistance = getDistance(event.touches);
    },
    onImageTouchStart: function onImageTouchStart(event) {
      const { touches } = event;

      const _ref2 = this.$refs.swipe || {};
      const _ref2$offsetX = _ref2.offsetX;
      const offsetX = _ref2$offsetX === void 0 ? 0 : _ref2$offsetX;

      if (touches.length === 1 && this.scale !== 1) {
        this.startMove(event);
      }
      /* istanbul ignore else */
      else if (touches.length === 2 && !offsetX) {
        this.startZoom(event);
      }
    },
    onImageTouchMove: function onImageTouchMove(event) {
      const { touches } = event;

      if (this.moving || this.zooming) {
        (0, _event.preventDefault)(event, true);
      }

      if (this.moving) {
        this.touchMove(event);
        const moveX = this.deltaX + this.startMoveX;
        const moveY = this.deltaY + this.startMoveY;
        this.moveX = (0, _number.range)(moveX, -this.maxMoveX, this.maxMoveX);
        this.moveY = (0, _number.range)(moveY, -this.maxMoveY, this.maxMoveY);
      }

      if (this.zooming && touches.length === 2) {
        const distance = getDistance(touches);
        const scale = this.startScale * distance / this.startDistance;
        this.setScale(scale);
      }
    },
    onImageTouchEnd: function onImageTouchEnd(event) {
      /* istanbul ignore else */
      if (this.moving || this.zooming) {
        let stopPropagation = true;

        if (this.moving && this.startMoveX === this.moveX && this.startMoveY === this.moveY) {
          stopPropagation = false;
        }

        if (!event.touches.length) {
          this.moving = false;
          this.zooming = false;
          this.startMoveX = 0;
          this.startMoveY = 0;
          this.startScale = 1;

          if (this.scale < 1) {
            this.resetScale();
          }
        }

        if (stopPropagation) {
          (0, _event.preventDefault)(event, true);
        }
      }
    },
    setActive: function setActive(active) {
      this.resetScale();

      if (active !== this.active) {
        this.active = active;
        this.$emit('change', active);
      }
    },
    setScale: function setScale(scale) {
      const value = (0, _number.range)(scale, +this.minZoom, +this.maxZoom);
      this.scale = value;
      this.$emit('scale', {
        index: this.active,
        scale: value,
      });
    },
    resetScale: function resetScale() {
      this.setScale(1);
      this.moveX = 0;
      this.moveY = 0;
    },
    toggleScale: function toggleScale() {
      const scale = this.scale > 1 ? 1 : 2;
      this.setScale(scale);
      this.moveX = 0;
      this.moveY = 0;
    },
    genIndex: function genIndex() {
      const h = this.$createElement;

      if (this.showIndex) {
        return h('div', {
          class: bem('index'),
        }, [this.slots('index') || `${this.active + 1} / ${this.images.length}`]);
      }
    },
    genCover: function genCover() {
      const h = this.$createElement;
      const cover = this.slots('cover');

      if (cover) {
        return h('div', {
          class: bem('cover'),
        }, [cover]);
      }
    },
    genImages: function genImages() {
      const _this4 = this;

      const h = this.$createElement;
      const imageSlots = {
        loading: function loading() {
          return h(_loading.default, {
            attrs: {
              type: 'spinner',
            },
          });
        },
      };
      return h(_swipe.default, {
        ref: 'swipe',
        attrs: {
          lazyRender: true,
          loop: this.loop,
          indicatorColor: 'white',
          duration: this.swipeDuration,
          initialSwipe: this.startPosition,
          showIndicators: this.showIndicators,
        },
        class: bem('swipe'),
        on: {
          change: this.setActive,
        },
      }, [this.images.map((image, index) => h(_swipeItem.default, [h(_image.default, {
        attrs: {
          src: image,
          fit: 'contain',
        },
        class: bem('image'),
        scopedSlots: imageSlots,
        style: index === _this4.active ? _this4.imageStyle : null,
        nativeOn: {
          touchstart: _this4.onImageTouchStart,
          touchmove: _this4.onImageTouchMove,
          touchend: _this4.onImageTouchEnd,
          touchcancel: _this4.onImageTouchEnd,
        },
      })]))]);
    },
    genClose: function genClose() {
      const h = this.$createElement;

      if (this.closeable) {
        return h(_icon.default, {
          attrs: {
            role: 'button',
            name: this.closeIcon,
          },
          class: bem('close-icon', this.closeIconPosition),
          on: {
            click: this.emitClose,
          },
        });
      }
    },
    onClosed: function onClosed() {
      this.$emit('closed');
    },
  },
  render: function render() {
    const h = arguments[0];

    if (!this.shouldRender) {
      return;
    }

    return h('transition', {
      attrs: {
        name: 'van-fade',
      },
      on: {
        afterLeave: this.onClosed,
      },
    }, [h('div', {
      directives: [{
        name: 'show',
        value: this.value,
      }],
      class: [bem(), this.className],
    }, [this.genClose(), this.genImages(), this.genIndex(), this.genCover()])]);
  },
});

exports.default = _default2;
